import tkinter as tk
from tkinter import scrolledtext, font
import time
import os
import threading

class LogViewerApp:
    def __init__(self, root, log_file='app.log', max_lines=100):
        self.root = root
        self.root.title("日志查看器")
        self.root.configure(bg="#f0f0f0")
        
        self.log_file = log_file
        self.max_lines = max_lines
        self.last_mtime = 0
        self.stop_event = threading.Event()
        
        # 设置字体，确保中文正常显示
        self.font_family = ("SimHei", "WenQuanYi Micro Hei", "Heiti TC", "Arial")
        self.text_font = font.Font(family=self.font_family[0], size=10)
        self.header_font = font.Font(family=self.font_family[0], size=12, weight="bold")
        
        # 获取屏幕尺寸并设置窗口位置（宽度400，高度800，贴屏幕最右边）
        screen_width = self.root.winfo_screenwidth()
        self.root.geometry(f"400x800+{screen_width-400}+0")
        
        self.create_widgets()
        self.start_log_monitor()
    
    def create_widgets(self):
        # 顶部信息栏
        top_frame = tk.Frame(self.root, bg="#4a7abc", height=40)
        top_frame.pack(fill=tk.X)
        
        title_label = tk.Label(top_frame, text="日志实时监控", font=self.header_font, 
                              bg="#4a7abc", fg="white")
        title_label.pack(pady=10)
        
        # 日志显示区域
        self.log_area = scrolledtext.ScrolledText(self.root, wrap=tk.WORD, 
                                                  font=self.text_font, bg="black", fg="#00ff00")
        self.log_area.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
        
        # 状态栏
        status_frame = tk.Frame(self.root, bg="#e0e0e0", height=25)
        status_frame.pack(fill=tk.X, side=tk.BOTTOM)
        
        self.status_label = tk.Label(status_frame, text=f"监控文件: {self.log_file}", 
                                    font=("Arial", 9), bg="#e0e0e0")
        self.status_label.pack(side=tk.LEFT, padx=10, pady=5)
        
        # 添加刷新按钮
        self.refresh_btn = tk.Button(status_frame, text="刷新", command=self.refresh_logs,
                                    bg="#d0d0d0", relief=tk.FLAT, cursor="hand2")
        self.refresh_btn.pack(side=tk.RIGHT, padx=10, pady=2)
    
    def refresh_logs(self):
        """手动刷新日志"""
        self.display_logs()
    
    def tail_logs(self):
        """读取日志文件最后N行"""
        try:
            if not os.path.exists(self.log_file):
                return ["日志文件不存在: " + self.log_file]
            
            # 获取文件修改时间
            current_mtime = os.path.getmtime(self.log_file)
            
            # 如果文件没有变化，不重读
            if current_mtime == self.last_mtime:
                return None
            
            self.last_mtime = current_mtime
            
            # 读取最后N行
            with open(self.log_file, 'r', encoding='utf-8') as f:
                lines = f.readlines()
            
            # 取最后max_lines行并反转
            return lines[-self.max_lines:][::-1]
            
        except Exception as e:
            return [f"读取日志出错: {str(e)}"]
    
    def display_logs(self):
        """在界面上显示日志"""
        log_lines = self.tail_logs()
        if log_lines is None:
            return  # 文件没有变化
        
        self.log_area.delete(1.0, tk.END)  # 清空文本区域
        
        for line in log_lines:
            self.log_area.insert(tk.END, line.strip() + "\n")
        
        # 滚动到顶部（最新日志）
        self.log_area.see(1.0)
    
    def monitor_logs(self):
        """后台监控日志文件变化"""
        while not self.stop_event.is_set():
            self.display_logs()
            time.sleep(1)  # 每秒检查一次
    
    def start_log_monitor(self):
        """启动日志监控线程"""
        self.log_thread = threading.Thread(target=self.monitor_logs)
        self.log_thread.daemon = True
        self.log_thread.start()
    
    def on_closing(self):
        """关闭应用时清理资源"""
        self.stop_event.set()
        self.root.destroy()

if __name__ == "__main__":
    root = tk.Tk()
    app = LogViewerApp(root)
    root.protocol("WM_DELETE_WINDOW", app.on_closing)
    root.mainloop()